import {
  CanActivate,
  ExecutionContext,
  Injectable,
  Logger,
} from "@nestjs/common";
import { WsException } from "@nestjs/websockets";
import { WebSocket } from "ws";

@Injectable()
export class WsAuthGuard implements CanActivate {
  private readonly logger = new Logger(WsAuthGuard.name);

  canActivate(context: ExecutionContext): boolean {
    try {
      const client: WebSocket = context.switchToWs().getClient();
      const request = (client as any).request;

      // 从查询参数中获取token
      const token = request?.query?.token || request?.query?.t;

      if (!token) {
        this.logger.warn("WebSocket连接缺少token");
        throw new WsException("未授权访问：缺少认证token");
      }

      // 确保token是字符串类型
      if (typeof token !== "string") {
        this.logger.error(
          `Token类型错误: 期望string，实际${typeof token}`,
          token
        );
        throw new WsException("未授权访问：token格式错误");
      }

      // 验证token（这里应该调用实际的token验证服务）
      const isValid = this.validateToken(token);

      if (!isValid) {
        this.logger.warn(`WebSocket连接token无效: ${token}`);
        throw new WsException("未授权访问：token无效");
      }

      // 从token中提取用户信息并存储到Socket中
      const userInfo = this.extractUserInfoFromToken(token);
      if (userInfo) {
        (client as any).data = {
          ...(client as any).data,
          userId: userInfo.userId,
          userName: userInfo.userName,
          characterId: userInfo.characterId,
        };
      }

      this.logger.log(`WebSocket用户认证成功: userId=${userInfo?.userId}`);
      return true;
    } catch (error: any) {
      this.logger.error("WebSocket认证失败:", error?.message || error);
      throw new WsException("认证失败");
    }
  }

  /**
   * 验证token有效性
   * 这里应该调用实际的token验证服务
   */
  private validateToken(token: string): boolean {
    try {
      // 临时实现：检查token格式
      if (!token || token === "undefined" || token === "null") {
        return false;
      }

      // 如果是测试token，直接通过
      if (token.startsWith("test-token-")) {
        return true;
      }

      // 这里应该调用实际的token验证服务
      // 例如：return this.authService.validateToken(token);

      // 临时返回true，实际应该根据验证结果返回
      return true;
    } catch (error: any) {
      this.logger.error("Token验证失败:", error?.message || error);
      return false;
    }
  }

  /**
   * 从token中提取用户信息
   * 这里应该调用实际的token解析服务
   */
  private extractUserInfoFromToken(token: string): any {
    try {
      // 临时实现：从测试token中提取用户信息
      if (token.startsWith("test-token-")) {
        // 测试token格式：test-token-123456789
        const userId = parseInt(token.replace("test-token-", ""));
        return {
          userId: userId || 1,
          userName: `测试用户${userId || 1}`,
          characterId: 1,
        };
      }

      // 这里应该调用实际的token解析服务
      // 例如：return this.authService.decodeToken(token);

      // 临时返回默认用户信息
      return {
        userId: 1,
        userName: "默认用户",
        characterId: 1,
      };
    } catch (error: any) {
      this.logger.error("Token解析失败:", error?.message || error);
      return null;
    }
  }
}
